home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / metasploit / msfelfscan < prev    next >
Text File  |  2006-06-30  |  7KB  |  285 lines

  1. #!/usr/bin/perl
  2. ###############
  3.  
  4. ##
  5. #         Name: msfelfscan
  6. #       Author: Richard Johnson <rjohnson [at] uninformed.org>
  7. #      Version: $Revision: 1.5 $
  8. #  Description: Search ELF files for given opcodes
  9. #      License:
  10. #
  11. #      This file is part of the Metasploit Exploit Framework
  12. #      and is subject to the same licenses and copyrights as
  13. #      the rest of this package.
  14. #
  15. ##
  16.  
  17. require 5.6.0;
  18.  
  19. use FindBin qw{$RealBin};
  20. use lib "$RealBin/lib";
  21. use Getopt::Std;
  22. use strict;
  23.  
  24. use Pex::ELFInfo;
  25. use Pex::Nasm::Ndisasm;
  26. use Pex;
  27.  
  28. use Msf::ColPrint;
  29. use Msf::TextUI;
  30.  
  31. no utf8;
  32. no locale;
  33.  
  34. Msf::UI::ActiveStateSucks();
  35. Msf::UI::BrokenUTF8();
  36.  
  37. my $VERSION = '$Revision: 1.5 $';
  38.  
  39. my %opts = ();
  40. my %jmps =
  41.     (
  42.         "\xff\xd0" => ["eax", "call"],
  43.         "\xff\xe0" => ["eax", "jmp" ],
  44.         "\xff\xd1" => ["ecx", "call"],
  45.         "\xff\xe1" => ["ecx", "jmp" ],
  46.         "\xff\xd2" => ["edx", "call"],
  47.         "\xff\xe2" => ["edx", "jmp" ],
  48.         "\xff\xd3" => ["ebx", "call"],
  49.         "\xff\xe3" => ["ebx", "jmp" ],
  50.         "\xff\xe4" => ["esp", "jmp" ],
  51.         "\xff\xd5" => ["ebp", "call"],
  52.         "\xff\xe5" => ["ebp", "jmp" ],
  53.         "\xff\xd6" => ["esi", "call"],
  54.         "\xff\xe6" => ["esi", "jmp" ],
  55.         "\xff\xd7" => ["edi", "call"],
  56.         "\xff\xe7" => ["edi", "jmp" ],
  57.         
  58.         "\x50\xc3" => ["eax", "push"],
  59.         "\x53\xc3" => ["ebx", "push"],
  60.         "\x51\xc3" => ["ecx", "push"],
  61.         "\x52\xc3" => ["edx", "push"],
  62.         "\x54\xc3" => ["esp", "push"],
  63.         "\x55\xc3" => ["ebp", "push"],
  64.         "\x56\xc3" => ["esi", "push"],
  65.         "\x57\xc3" => ["edi", "push"],
  66.     );
  67.  
  68. my %pops =
  69.     (
  70.         "eax"   => "\x58",
  71.         "ebx"   => "\x5b",
  72.         "ecx"   => "\x59",
  73.         "edx"   => "\x5a",
  74.         "esi"   => "\x5e",
  75.         "edi"   => "\x5f",
  76.         "ebp"   => "\x5d",
  77.     );
  78.  
  79.  
  80. getopts("f:d:j:sx:a:B:A:I:nhvED", \%opts);
  81. Usage()   if($opts{'h'});
  82. Version() if($opts{'v'});
  83.  
  84. if ($opts{'h'} || 
  85.      (! defined($opts{'f'}) && ! defined($opts{'d'})) ||
  86.      (! defined($opts{'j'}) &&
  87.       ! defined($opts{'x'}) &&
  88.       ! defined($opts{'a'}) && 
  89.       ! defined($opts{'D'}) && 
  90.       ! $opts{'s'})
  91.    ) 
  92.    Usage(); 
  93.    exit(0); 
  94. }
  95.  
  96. my $func;
  97. my $args = { };
  98.  
  99. if(exists($opts{'s'})) {
  100.   $func = \&popPopRet;
  101. }
  102. elsif(exists($opts{'j'})) {
  103.   $func = \&jmpReg;
  104.   $args->{'reg'} = $opts{'j'};
  105. }
  106. elsif(exists($opts{'x'})) {
  107.   $func = \®ex;
  108.   $args->{'regex'} = $opts{'x'};
  109. }
  110. elsif(exists($opts{'a'})) {
  111.   $func = \&address;
  112.   $args->{'address'} = hex($opts{'a'});
  113. }
  114. elsif(exists($opts{'D'})) {
  115.   $func = \&dumpinfo;
  116.   $args->{'dumpinfo'} = hex($opts{'D'});
  117. }
  118.  
  119. $args->{'before'} = $opts{'B'} if(exists($opts{'B'}));
  120. $args->{'after'} = $opts{'A'} if(exists($opts{'A'}));
  121.  
  122. if($opts{'f'}) {
  123.  
  124.   my $filename = $opts{'f'};
  125.   my $elf = Pex::ELFInfo->new('File' => $filename, 'Debug' => $opts{'E'});
  126.   if (! $elf)
  127.   {
  128.       print STDERR "$0: could not load ELF image from file.\n";
  129.       exit(0);
  130.   }
  131.   if ($opts{'I'}) { $elf->ImageBase($opts{'I'}) }
  132.   &{$func}($elf, $args);
  133. }
  134.  
  135. sub dumpinfo {
  136.     my $elf = shift;
  137.     my $args = shift;
  138.     my $col;
  139.     my @Ehdr     = $elf->ElfHeaders;
  140.     my @Phdr   = $elf->ProgramHeaders;
  141.     
  142.     print "\n\n[ ELF Header ]\n\n";
  143.     $col = Msf::ColPrint->new(4, 4);
  144.     foreach my $hdr (@Ehdr) {
  145.         $col->AddRow($hdr, sprintf("0x%.8x",$elf->ElfHeader($hdr)));
  146.     }
  147.     print $col->GetOutput;
  148.  
  149.     print "\n\n[ Program Headers ]\n\n";
  150.     my $e_phnum = $elf->ElfHeader("e_phnum");
  151.     for(my $i = 0; $i < $e_phnum; $i++)
  152.     {        
  153.     $col = Msf::ColPrint->new(4, 4);
  154.         foreach my $hdr (@Phdr) {
  155.             $col->AddRow($hdr, sprintf("0x%.8x",$elf->ProgramHeader($i, $hdr)));
  156.         }
  157.     print $col->GetOutput;
  158.     printf("\n----\n");
  159.     }
  160.     
  161. }
  162.  
  163.  
  164. # Scan for pop/pop/ret addresses
  165. sub popPopRet
  166. {
  167.     my $elf = shift;
  168.     my $data = $elf->Raw;
  169.     my $args = shift;
  170.     foreach my $rA (keys(%pops))
  171.     {
  172.         foreach my $rB (keys(%pops))
  173.         {
  174.             my $opc = $pops{$rA} . $pops{$rB} . "\xc3";
  175.             my $lst = 0;
  176.             my $idx = index($data,  $opc, $lst);
  177.             while ($idx > 0)
  178.             {
  179.                 printf("0x%.8x   $rA $rB ret\n", $elf->OffsetToVirtual($idx));
  180.                 $lst = $idx + 1;
  181.                 $idx = index($data, $opc, $lst);
  182.             }
  183.         }
  184.     }
  185. }
  186.  
  187. # Scan for jmp/call/push,ret addresses
  188. sub jmpReg
  189. {
  190.     my $elf = shift;
  191.     my $data = $elf->Raw;
  192.     my $args = shift;
  193.     my $reg = $args->{'reg'};
  194.     foreach my $opc (keys(%jmps))
  195.     {
  196.         next if ($reg && lc($reg) ne $jmps{$opc}->[0]);
  197.  
  198.         my $lst = 0;
  199.         my $idx = index($data, $opc, $lst);
  200.         while ($idx > 0)
  201.         {
  202.             my ($reg, $typ) = @{$jmps{$opc}};
  203.             printf("0x%.8x   $typ $reg\n", $elf->OffsetToVirtual($idx));
  204.             $lst = $idx + 1;
  205.             $idx = index($data, $opc, $lst);
  206.         }
  207.     }
  208. }
  209.  
  210. # Regex
  211. sub regex {
  212.   my $elf = shift;
  213.   my $data = $elf->Raw;
  214.   my $args = shift;
  215.   my $regex = $args->{'regex'};
  216.   $regex .= '.' x $args->{'after'} if($args->{'after'});
  217.   $regex = ('.' x $args->{'before'}) . $regex if($args->{'before'});
  218.  
  219.   while($data =~ m/($regex)/g) {
  220.     my $found = $1;
  221.     my $index = pos($data) - length($found);
  222.     printf("0x%.8x   %s\n", $elf->OffsetToVirtual($index), hexOutput($found));
  223.   }
  224. }
  225.  
  226. sub address {
  227.   my $elf = shift;
  228.   my $data = $elf->Raw;
  229.   my $args = shift;
  230.  
  231.   my $address = $args->{'address'} - $args->{'before'};
  232.   my $length = $args->{'before'} + $args->{'after'};
  233.   $length = 1 if(!$length);
  234.   my $index = $elf->VirtualToOffset($address);
  235.   my $found = substr($data, $index, $length);
  236.   return if(!defined($index) || length($found) == 0);
  237.   printf("0x%.8x   %s\n", $address, hexOutput($found));
  238. }
  239.  
  240. sub hexOutput {
  241.   my $data = shift;
  242.   my $string = unpack('H*', $data);
  243.   if($opts{'n'}) {
  244. #    my $tempString = $string;
  245. #    $tempString =~ s/(..)/\\x$1/g;
  246.     $string .= "\n--- ndisasm output ---\n";
  247. #    $string .= `echo -ne "$tempString" | ndisasm -u /dev/stdin`;
  248.     $string .= Pex::Nasm::Ndisasm->DisasData($data);
  249.     $string .= "--- ndisasm output ---";
  250.   }
  251.   return($string);
  252. }
  253.  
  254.  
  255. sub Usage 
  256. {
  257.     print STDERR
  258. qq{  Usage: $0 <input> <mode> <options>
  259. Inputs:
  260.          -f  <file>    Read in ELF file
  261. Modes:
  262.          -j  <reg>     Search for jump equivalent instructions
  263.          -s            Search for pop+pop+ret combinations
  264.          -x  <regex>   Search for regex match
  265.          -a  <address> Show code at specified virtual address
  266. Options:
  267.          -A  <count>   Number of bytes to show after match
  268.          -B  <count>   Number of bytes to show before match
  269.          -I  address   Specify an alternate base load address
  270.          -n            Print disassembly of matched data
  271. };
  272.   exit(0);
  273.  
  274. }
  275. sub Version {
  276.     my $ver = Pex::Utils::Rev2Ver($VERSION);
  277.     print STDERR qq{
  278.    Msfelfscan Version:  $ver 
  279.  
  280. };
  281.   exit(0);
  282. }
  283.  
  284.